#ifndef _ll_include_h
#define _ll_include_h

#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <stdint.h>
#include <sys/queue.h>
#include "scps.h"
#include "scpstp.h"

#ifndef   IPPROTO_DIVERT
#define   IPPROTO_DIVERT      254
#endif    /* IPPROTO_DIVERT */

#define MAX_LL_QUEUE_ELEMENTS 1000
#define SCPS_UDP_PORT  7168
#define Other_SCPS_UDP_PORT 7167        /* Added for loopback testing */
#define SCPS_SPANNER_PORT 7169

#define MAC_ADDR_SIZE 6
#define START_OF_FRAME_TYPE 12
#define SIZE_OF_ETHER_PART 14

fd_set llfd_set;
int ll_max_socket;

struct llbuf {
  uint8_t data[MAX_LL_DATA];
  
  TAILQ_ENTRY(llbuf) entry;

  int pool;
  int size;
  int offset;
  
  
  uint8_t *l2_ptr;
  int l2_size;
  
  uint8_t *l3_ptr;
  int l3_size;
  
  uint8_t *l4_ptr;
  int l4_size;

  uint8_t src_mac [ETH_ALEN];
  uint8_t dst_mac [ETH_ALEN];
  
  uint32_t saddr, daddr;
  uint8_t protocol;
  uint8_t version;
  uint16_t frame_type;
  int frame_size;
  struct gwio *gwio;
  int32_t divert_port_number;
  int recv_tap_if;
  int in;
  int out;
};

struct gwio {
  TAILQ_HEAD(incoming_head, llbuf) incoming;
  TAILQ_HEAD(outgoing_head, llbuf) outgoing;
  TAILQ_HEAD(available_head, llbuf) available;
  struct gwio *next;
  int MTU;
  uint32_t address;
  uint32_t next_hop;        /* USED only for DIVERT_N_RAWIP */
  int tp_socket, np_socket, et_socket;
  int tap_a_fd;
  int tap_b_fd;
  int32_t div_port;
  int32_t div_a_port;
  int32_t div_b_port;
  int is_free, service_now;
  int overhead;
  int mss_ff;
};

/* Function prototypes for lower layer stuff */
int get_local_internet_addr (char *storage);
int32_t get_remote_internet_addr (char *host);

uint32_t clock_ValueRough (void);

void gwio_init (struct gwio *gwio, uint32_t local_addr);

struct llbuf *alloc_llbuff (struct gwio *gwio);
void free_llbuf (struct gwio *gwio, struct llbuf *buffer);


void service_interface (struct gwio *gwio);
int ll_iovsend (struct gwio *gwio, struct addrs addr,
      int protocol, int data_len, struct msghdr *my_msg,
      route *a_route, scps_np_rqts *rqts);
int ll_send (uint32_t remote_internet_addr, byte * data, int data_len);
int ll_nbreceive (struct gwio *gwio, struct llbuf **buffer, int max_len, int *offset);
void create_divert_interface (uint32_t spanner_local_addr, int32_t port_number1);

struct llbuf *gwio_rx(struct gwio *gwio, int fd);

extern struct gwio *divert_gwio;

#define ET_MAGIC        100  /* MAGIC NUMBER FOR et_socket */
void ll_show(void);
void ll_set_udp_port(uint16_t port);
void ll_set_udp_port1(uint16_t port);

#endif /* _ll_include_h */
